import { reactive, watch, nextTick } from 'vue'
import { merge } from 'lodash'
import { clearQueryParams } from './../utils.js'

export default class tableList {
  /**
   * 列表组件
   * @param {number} api - 当前行号
   * @param {boolen} init - 是否初始化 默认是 true
   * @param {object} queryForm - 当前行号
   * @param {object} queryFormConfig - 当前行号
   * @returns {number} 计算后的序列号
   */
  constructor({ api, init = true, queryForm = {}, columns = [], rules = {}, queryFormConfig = {}, formRef, tableRef } = {}) {
    this.data = reactive({
      createInit: init, // 创建初始化
      initActivated: false, // keep-live 再次激活 刷新数据
      getListDataApi: api, // 获取数据的API
      queryForm: merge({ pageNum: 1, pageSize: 10, orderBy: '', loading: false, total: 0 }, queryForm), // 查询用数据
      queryRules: merge({}, rules), // 查询校验
      tableList: [], // 表格数据
      multipleSelection: [], // 多选数据
      showSearch: true, // 是否显示查询
      columns: columns, // 表格列配置
      columnsShow: {}, // 列显示配置
      ids: [], // 当前选中的id
      single: true, // 单选模式
      multiple: true, // 多选模式
      queryFormRef: formRef, // 查询表单
      dataTableRef: tableRef, // 展示列表
      queryFormConfig: merge({
        rowKey: 'id',
        paramConfig: { // 提交参数数据根据这个对象配置进行区分的参数类型 { params: [], path: [], body: [] }
          params: [],
          path: [],
          body: []
        },
        getDataClearKeys: [], // 查询数据自定义清理的数据处理 需要清理的 formData k
        getDataBeforeFormat: null, // 查询数据自定义数据处理 Function 示例 (k,v) => v
        getDataAfterFormat: null, // 获取数据后前置列表数据格式化 Function 示例 (listData) => {}
        afterFormReset: null, // 查询数据重置 Function 示例 () => {}
        customSetList: null, // 自定义设置列表数据 Function 示例 (listData) => {
        sortByPropAlias: (v) => v // 远程排序点击 别名处理 需要的时候-用户重写
      }, queryFormConfig), // 查询数据处理配置
      selectKeys: [] // 数据可选
    })
    this.data.createInit && this.tableListData()
    this.data.firstCreatedRender = true
    nextTick(() => {
      this.data.firstCreatedRender = false
    })
    watch(() => this.data.columns, (v) => {
      this.data.columnsShow = v.reduce((o, n) => {
        o[n.prop] = n.visible
        return o
      }, {})
    }, { deep: true, immediate: true })
    watch(() => this.data.queryForm.pageNum, (v) => {
      this.bindPageChange(v)
    })
    watch(() => this.data.queryForm.pageSize, (v) => {
      this.bindPageSizeChange(v)
    })
  }

  /**
   * 自定义索引 返回根据当前的序号、分页数据计算后的序列号
   * @param {number} index - 当前行号
   * @example <el-table-column label="序号" type="index" :index="indexMethod">
   * @returns {number} 计算后的序列号
   */
  indexMethod(index) {
    const { pageNum, pageSize } = this.data.queryForm
    return pageSize * (pageNum - 1) + index + 1
  }
  // 更新当前UI example 列表更新
  updateSelectListUI() {
    nextTick(() => {
      for (const it of this.data.multipleSelection) {
        for (const ct of this.data.dataTableRef) {
          if (it.id === ct.id) {
            this.data.dataTableRef.toggleRowSelection(ct, true)
            break
          }
        }
      }
    })
  }
  // 多选变化 example <el-table row-key="id" @selection-change="bindSelectionChange"><el-table-column type="selection" width="55"></el-table-column></el-table>
  // <el-table-column type="selection" reserve-selection width="55"></el-table-column> 在数据更新之后保留之前选中的数据（需指定 row-key）
  bindSelectionChange(val) {
    const rowKey = this.data.queryFormConfig.rowKey
    this.data.multipleSelection = val // 当前选中的数据
    this.data.ids = val.map(item => item[rowKey]) // 当前选中的ids
    this.data.single = val.length != 1 // 当前是否单选
    this.data.multiple = !val.length // 当前是否多选
  }
  // <el-table-column type="selection" reserve-selection :selectable="rowSelectableDisabled" width="55"></el-table-column> 控制多选是否可选 默认根据提供的selectKeys属性集合和row的id属性排除
  rowSelectableDisabled(row, index) {
    return this.data.selectKeys.indexOf(this.data.queryFormConfig.rowKey) === -1
  }
  // 远程排序点击 example <el-table row-key="id" @sort-change="bindTableSort"><el-table-column prop="date" sort-by="date" label="日期" sortable="custom"></el-table-column></el-table>
  bindTableSort({ column, prop, order }) {
    // 根据排序字段请求接口
    const reg = new RegExp('ending', '')
    const a = order ? order.replace(reg, '') : ''
    this.data.queryForm.pageNum = 1
    this.data.queryForm.orderBy = column ? (this.data.queryFormConfig.sortByPropAlias(column.sortBy || prop)) + ' ' + a : ''
    // 请求接口
    this.tableListData()
  }
  // 远程筛选点击 example <el-table row-key="id" @filter-change="bindTableFilter"><el-table-column prop="date" column-key="date" label="日期" :filters="[{ text: '家', value: '家' }, { text: '公司', value: '公司' }]"></el-table-column></el-table>
  bindTableFilter(args) {
    for (const key in args) {
      if (Object.hasOwnProperty.call(this.data.queryForm, key)) {
        this.data.queryForm[key] = args[key].join(',')
      }
    }
    // 请求接口
    this.tableListData()
  }
  // 页码改变
  bindPageChange(pageNum) {
    this.data.queryForm.pageNum = pageNum
    // 请求接口
    this.tableListData()
  }
  // 每页大小改变
  bindPageSizeChange(pageSize) {
    this.data.queryForm.pageNum = 1
    this.data.queryForm.pageSize = pageSize
    // 请求接口
    this.tableListData()
  }
  // 数据清理
  getQueryFormData() {
    const queryFormConfig = this.data.queryFormConfig
    const paramConfig = queryFormConfig.paramConfig
    const formData = clearQueryParams(this.data.queryForm, queryFormConfig.getDataClearKeys, queryFormConfig.getDataBeforeFormat)
    // 使用reduce简化分类逻辑
    const classifiedData = Object.keys(formData).reduce((acc, key) => {
      if (paramConfig?.params.includes(key)) {
        acc.params = acc.params || {};
        acc.params[key] = formData[key];
      } else if (paramConfig?.path.includes(key)) {
        acc.path = acc.path || {};
        acc.path[key] = formData[key];
      } else if (paramConfig?.body.includes(key)) {
        acc.body = acc.body || {};
        acc.body[key] = formData[key];
      }
      return acc;
    }, {})
    // 如果classifiedData有内容，则返回它；否则返回原始formData
    return Object.keys(classifiedData).length ? classifiedData : formData
  }
  // 数据查询
  tableListData() {
    if (this.data.getListDataApi) {
      const queryFormConfig = this.data.queryFormConfig
      this.data.queryForm.loading = true
      const req = this.data.getListDataApi(this.getQueryFormData())
      req.then(({ result, rows, data, total }) => {
        const list = rows || (data?.records) || data || result.list || result || []
        const tempTotal = parseInt(total || (data?.total) || result.total || 0)
        queryFormConfig.getDataAfterFormat && queryFormConfig.getDataAfterFormat(list)
        if (queryFormConfig.customSetList) {
          queryFormConfig.customSetList(list)
        } else {
          this.data.tableList = list
          this.data.queryForm.total = tempTotal
        }
        this.data.queryForm.loading = false
      }).catch(() => {
        this.data.queryForm.loading = false
        this.data.tableList = []
        this.data.queryForm.total = 0
      })
    } else {
      console.error('Configure the getListDataApi property of the data object, which is a Promise request object.')
    }
  }
  // 查询按钮绑定事件方法
  handleTableGetList() {
    this.data.queryForm.pageNum = 1
    if (this.data.queryFormRef) {
      this.data.queryFormRef.validate((valid) => {
        if (valid) {
          this.tableListData()
        }
      })
    } else {
      this.tableListData()
    }
  }
  // 重置清除按钮绑定方法
  handleQueryFormReset() {
    this.data.queryFormRef && this.data.queryFormRef.resetFields()
    if (this.data.dataTableRef) {
      this.data.dataTableRef.clearSort()
      this.data.dataTableRef.clearFilter()
      this.data.dataTableRef.clearSelection()
    }
    // 清除数据 后调用自定义方法
    this.data.queryFormConfig.afterFormReset && this.data.queryFormConfig.afterFormReset()
    // 请求接口
    this.tableListData()
  }

  setDefault(t) {
    for (const key in t) {
      if (Object.hasOwnProperty.call(this.data.queryForm, key)) {
        this.data.queryForm[key] = t[key]
      }
    }
    this.data.queryForm.pageNum = 1
    this.data.queryForm.pageSize = 10
    // 请求接口
    this.tableListData()
  }
  dictDisplay(r, c, v, i) {
    return v !== '' ? r[`${c.property}Display`] : v
  }
}